Golangで構造体を使ったJSON操作で出来ることを調べてみた
西田@大阪です。
Golangでできる構造体を使ったJSON操作を調べてみました。
struct tags
Golangでは structタグでJSONの処理をある程度制御することができます。
記述例
type Sample struct { // json:<マッピングするJSONオブジェクトのフィールド名>,<オプション> という形式で記述します FieldName string `json:"field_name,string"` }
用意されているオプションは以下の通りです。
タグ | Marshal(JSON出力)時 | Unmarshal(JSONパース)時 | 例 |
---|---|---|---|
omitempty | 0値(空文字、0、nil等)であればフィールドを出力しない | 0値であれば無視される | json:"field,omitempty" |
- | 出力しない | 無視される | json:"-" |
string | 出力時に Quote される |
Quote されていても型に合わせて変換する。Quote されてないとエラー |
json:"field,string" |
type JSONSample struct { Field string `json:"field"` Omit string `json:"-"` OmitEmpty string `json:"omit_empty,omitempty"` Num int `json:"num,string"` } func main() { sample := JSONSample{ Field: "field", Omit: "omit", OmitEmpty: "", Num: 1, } bytes, _ := json.Marshal(&sample) fmt.Println(string(bytes)) /* -- output { "field": "field", "num":"1" } - omitは省略されています - omit_emptyは値がないので、JSONではフィールドごと省略されてます - numは Golangではint型ですが、JSONではstructタグでstringが指定されているのでQuoteされて出力されています */ j := ` { "field": "field", "omit": "omit", "omit_empty": "a", "num": "123" } ` var decoded JSONSample json.Unmarshal([]byte(j), &decoded) fmt.Printf("%v\n", decoded) /* -- output {field a 123} - omitは値があってもけされています - emit_emptyは値があるので、構造体に値として設定されています - numはJSONでは文字列ですが、structタグで設定 string を設定されているので構造体の型であるintに変換されてます */ }
カスタム
structタグのみでできない処理は MarshalJSON
UnmarshalJSON
関数を定義しカスタムすることが可能です。
例えば、time.Time
型は RFC3339(2006-01-02T15:04:05Z07:00) しか time.Time
型に変換できないですが、MarshalJSON
UnmarshalJSON
メソッドを定義することによって、別の日付のフォーマットでも取り扱うことが可能です。
下記は 2017/09/05
のようなフォーマットで日付を扱いたい場合の例です。
// 新しい構造体を宣言します。元の構造体と同じように扱いたいので embedded してます type MyTime struct { *time.Time } // Unmarshal時の動作を定義します func (mt *MyTime) UnmarshalJSON(data []byte) error { // 要素がそのまま渡ってくるので "(ダブルクォート)でQuoteされてます t, err := time.Parse("\"2006/01/02\"", string(data)) *mt = MyTime{&t} return err } // Marshal時の動作を定義します func (mt MyTime) MarshalJSON() ([]byte, error) { return json.Marshal(mt.Format("2006/01/02")) }
type JSONSample struct { TimeAt MyTime `json:"time_at"` } func main() { j := ` { "time_at":"2017/09/12" } ` var decoded JSONSample json.Unmarshal([]byte(j), &decoded) fmt.Printf("%v\n", decoded) /* -- output {2017-09-12 00:00:00 +0000 UTC} */ j2, _ := json.Marshal(decoded) fmt.Printf("%v", string(j2)) /* -- output {"time_at":"2017/09/12"} */ }